﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Globalization
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    <Serializable> _
    Public Class Rule
        ' Methods
        Public Sub New()
            Me.behavior = RuleReevaluationBehavior.Always
            Me.active = True
        End Sub

        Public Sub New(ByVal name As String)
            Me.behavior = RuleReevaluationBehavior.Always
            Me.active = True
            Me.name = name
        End Sub

        Public Sub New(ByVal name As String, ByVal condition As RuleCondition, ByVal thenActions As IList([Of] RuleAction))
            Me.behavior = RuleReevaluationBehavior.Always
            Me.active = True
            Me.name = name
            Me.condition = condition
            Me.thenActions = thenActions
        End Sub

        Public Sub New(ByVal name As String, ByVal condition As RuleCondition, ByVal thenActions As IList([Of] RuleAction), ByVal elseActions As IList([Of] RuleAction))
            Me.behavior = RuleReevaluationBehavior.Always
            Me.active = True
            Me.name = name
            Me.condition = condition
            Me.thenActions = thenActions
            Me.elseActions = elseActions
        End Sub

        Private Shared Function ActionsEqual(ByVal myActions As IList([Of] RuleAction), ByVal otherActions As IList([Of] RuleAction)) As Boolean
            If ((Not myActions Is Nothing) OrElse (Not otherActions Is Nothing)) Then
                If ((myActions Is Nothing) OrElse (otherActions Is Nothing)) Then
                    Return False
                End If
                If (myActions.Count <> otherActions.Count) Then
                    Return False
                End If
                Dim i As Integer
                For i = 0 To myActions.Count - 1
                    If Not myActions.Item(i).Equals(otherActions.Item(i)) Then
                        Return False
                    End If
                Next i
            End If
            Return True
        End Function

        Public Function Clone() As Rule
            Dim rule As Rule = DirectCast(MyBase.MemberwiseClone, Rule)
            rule.runtimeInitialized = False
            If (Not Me.condition Is Nothing) Then
                rule.condition = Me.condition.Clone
            End If
            If (Not Me.thenActions Is Nothing) Then
                rule.thenActions = New List([Of] RuleAction)
                Dim action As RuleAction
                For Each action In Me.thenActions
                    rule.thenActions.Add(action.Clone)
                Next
            End If
            If (Not Me.elseActions Is Nothing) Then
                rule.elseActions = New List([Of] RuleAction)
                Dim action2 As RuleAction
                For Each action2 In Me.elseActions
                    rule.elseActions.Add(action2.Clone)
                Next
            End If
            Return rule
        End Function

        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            Dim rule As Rule = [TryCast](obj,Rule)
            If (rule Is Nothing) Then
                Return False
            End If
            If (((Me.Name <> rule.Name) OrElse (Me.Description <> rule.Description)) OrElse (((Me.Active <> rule.Active) OrElse (Me.ReevaluationBehavior <> rule.ReevaluationBehavior)) OrElse (Me.Priority <> rule.Priority))) Then
                Return False
            End If
            If (Me.Condition Is Nothing) Then
                If (Not rule.Condition Is Nothing) Then
                    Return False
                End If
            ElseIf Not Me.Condition.Equals(rule.Condition) Then
                Return False
            End If
            If Not Rule.ActionsEqual(Me.thenActions, rule.thenActions) Then
                Return False
            End If
            If Not Rule.ActionsEqual(Me.elseActions, rule.elseActions) Then
                Return False
            End If
            Return True
        End Function

        Public Overrides Function GetHashCode() As Integer
            Return MyBase.GetHashCode
        End Function

        Friend Sub OnRuntimeInitialized()
            Me.runtimeInitialized = True
        End Sub

        Friend Sub Validate(ByVal validation As RuleValidation)
            Dim count As Integer = validation.Errors.Count
            If String.IsNullOrEmpty(Me.name) Then
                validation.Errors.Add(New ValidationError(Messages.RuleNameMissing, &H540))
            End If
            If (Me.condition Is Nothing) Then
                validation.Errors.Add(New ValidationError(Messages.MissingRuleCondition, &H57D))
            Else
                Me.condition.Validate(validation)
            End If
            If (Not Me.thenActions Is Nothing) Then
                Rule.ValidateRuleActions(Me.thenActions, validation)
            End If
            If (Not Me.elseActions Is Nothing) Then
                Rule.ValidateRuleActions(Me.elseActions, validation)
            End If
            Dim errors As ValidationErrorCollection = validation.Errors
            If (errors.Count > count) Then
                Dim str As String = String.Format(CultureInfo.CurrentCulture, Messages.RuleValidationError, New Object() { Me.name })
                Dim num2 As Integer = errors.Count
                Dim i As Integer
                For i = count To num2 - 1
                    Dim error As ValidationError = errors.Item(i)
                    Dim error2 As New ValidationError((str & [error].ErrorText), [error].ErrorNumber, [error].IsWarning)
                    Dim entry As DictionaryEntry
                    For Each entry In [error].UserData
                        error2.UserData.Item(entry.Key) = entry.Value
                    Next
                    errors.Item(i) = error2
                Next i
            End If
        End Sub

        Private Shared Sub ValidateRuleActions(ByVal ruleActions As ICollection([Of] RuleAction), ByVal validator As RuleValidation)
            Dim flag As Boolean = False
            Dim flag2 As Boolean = False
            Dim action As RuleAction
            For Each action In ruleActions
                action.Validate(validator)
                If flag Then
                    flag2 = True
                End If
                If TypeOf action Is RuleHaltAction Then
                    flag = True
                End If
            Next
            If flag2 Then
                validator.Errors.Add(New ValidationError(Messages.UnreachableCodeHalt, &H54C, True))
            End If
        End Sub


        ' Properties
        Public Property Active As Boolean
            Get
                Return Me.active
            End Get
            Set(ByVal value As Boolean)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.active = value
            End Set
        End Property

        Public Property Condition As RuleCondition
            Get
                Return Me.condition
            End Get
            Set(ByVal value As RuleCondition)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.condition = value
            End Set
        End Property

        Public Property Description As String
            Get
                Return Me.description
            End Get
            Set(ByVal value As String)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.description = value
            End Set
        End Property

        <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property ElseActions As IList([Of] RuleAction)
            Get
                If (Me.elseActions Is Nothing) Then
                    Me.elseActions = New List([Of] RuleAction)
                End If
                Return Me.elseActions
            End Get
        End Property

        Public Property Name As String
            Get
                Return Me.name
            End Get
            Set(ByVal value As String)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.name = value
            End Set
        End Property

        Public Property Priority As Integer
            Get
                Return Me.priority
            End Get
            Set(ByVal value As Integer)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.priority = value
            End Set
        End Property

        Public Property ReevaluationBehavior As RuleReevaluationBehavior
            Get
                Return Me.behavior
            End Get
            Set(ByVal value As RuleReevaluationBehavior)
                If Me.runtimeInitialized Then
                    Throw New InvalidOperationException(SR.GetString("Error_CanNotChangeAtRuntime"))
                End If
                Me.behavior = value
            End Set
        End Property

        <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property ThenActions As IList([Of] RuleAction)
            Get
                If (Me.thenActions Is Nothing) Then
                    Me.thenActions = New List([Of] RuleAction)
                End If
                Return Me.thenActions
            End Get
        End Property


        ' Fields
        Friend active As Boolean
        Friend behavior As RuleReevaluationBehavior
        Friend condition As RuleCondition
        Friend description As String
        Friend elseActions As IList([Of] RuleAction)
        Friend name As String
        Friend priority As Integer
        Private runtimeInitialized As Boolean
        Friend thenActions As IList([Of] RuleAction)
    End Class
End Namespace

